﻿using AJWPFAdmin.Core.Enums;
using AJWPFAdmin.Core.GlobalEvents;
using AJWPFAdmin.Core.HardwareSDKS.FFmpeg;
using AJWPFAdmin.Core.HardwareSDKS.VzClient;
using AJWPFAdmin.Core.Interfaces;
using AJWPFAdmin.Core.Logger;
using AJWPFAdmin.Core.Utils;
using log4net;
using Masuit.Tools;
using Masuit.Tools.Reflection;
using Masuit.Tools.Security;
using Masuit.Tools.Systems;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
using Newtonsoft.Json.Linq;
using Prism.Commands;
using Prism.Events;
using Prism.Mvvm;
using SixLabors.ImageSharp.Drawing.Processing;
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Reflection;
using System.Reflection.Metadata;
using System.Runtime.InteropServices;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Interop;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Threading;

namespace AJWPFAdmin.Core.HardwareSDKS.Models
{
    public class DeviceInfo : BindableBase
    {
        private bool _canRender;
        private FFmpegRTSPCapture _videoCapture;

        /// <summary>
        /// 是否启用手动开闸录像
        /// </summary>
        public bool EnableVideoCapture
        {
            get; set;
        }

        /// <summary>
        /// 录像时长(秒)
        /// </summary>
        public double? VideoDuration
        {
            get; set;
        }

        /// <summary>
        /// 自动触发录像相机IN值
        /// </summary>
        public string AutoVideoCaptureINValue { get; set; }

        /// <summary>
        /// 是否启用IO2报警, 目前仅针对臻识有效
        /// </summary>
        public bool EnableIO2Alarm { get; set; }

        /// <summary>
        /// IO2报警延迟秒数,目前仅针对臻识有效
        /// </summary>
        public int IO2AlarmDelaySeconds { get; set; }

        /// <summary>
        /// 设备初始化成功后由 DeviceScreenViewModel 注入的
        /// </summary>
        public static IEventAggregator EventAggregator { get; set; }

        /// <summary>
        /// 设备初始化成功后由 DeviceScreenViewModel 注入的
        /// </summary>
        public static Func<IDbServiceBridge> DbServiceBridgeHandle { get; set; }

        /// <summary>
        /// 设备初始化成功后由 DeviceScreenViewModel 注入的, 写一些错误日志,好排查问题
        /// </summary>
        public static AJLog4NetLogger Logger { get; set; }

        public long Id { get; set; }

        private string _code;
        /// <summary>
        /// 设备编号
        /// </summary>
        public string Code
        {
            get { return _code; }
            set { SetProperty(ref _code, value); }
        }

        private WatchPositionType? _watchPosition;
        /// <summary>
        /// 监控部位类型
        /// </summary>
        public WatchPositionType? WatchPosition
        {
            get { return _watchPosition; }
            set { SetProperty(ref _watchPosition, value); }
        }

        private DeviceType _type;
        /// <summary>
        /// 设备编号
        /// </summary>
        public DeviceType Type
        {
            get { return _type; }
            set { SetProperty(ref _type, value); }
        }

        private SerialPortType _serialPortType;
        /// <summary>
        /// 设备串口号
        /// </summary>
        public SerialPortType SerialPort
        {
            get { return _serialPortType; }
            set { SetProperty(ref _serialPortType, value); }
        }

        private string _ip;
        /// <summary>
        /// 设备IP地址
        /// </summary>
        public string IP
        {
            get { return _ip; }
            set { SetProperty(ref _ip, value); }
        }


        /// <summary>
        /// 设备端口号
        /// </summary>
        public int Port { get; set; }

        /// <summary>
        /// 登录账户名
        /// </summary>
        public string LoginName { get; set; }

        /// <summary>
        /// 登录密码
        /// </summary>
        public string LoginPassword { get; set; }

        /// <summary>
        /// 进出方向类型,动态赋值
        /// </summary>
        public PassagewayDirection Direction { get; set; }

        protected string DeviceDescription
        {
            get
            {
                return $"{WatchhouseName}>{PassagewayName}>{Code}";
            }
        }

        private bool _mouseHover;
        public bool MouseHover
        {
            get { return _mouseHover; }
            set { SetProperty(ref _mouseHover, value); }
        }

        private CarIdentificationResult _carIdentificationResult;
        /// <summary>
        /// 当前识别的车牌信息
        /// </summary>
        public CarIdentificationResult CarIdentificationPlateResult
        {
            get { return _carIdentificationResult; }
            set { SetProperty(ref _carIdentificationResult, value); }
        }

        /// <summary>
        /// 关联岗亭id,动态赋值
        /// </summary>
        public long WatchhouseId { get; set; }

        /// <summary>
        /// 关联岗亭编号,动态赋值
        /// </summary>
        public string WatchhouseCode { get; set; }

        /// <summary>
        /// 关联岗亭名称,动态赋值
        /// </summary>
        public string WatchhouseName { get; set; }

        /// <summary>
        /// 关联通道id, 动态赋值
        /// </summary>
        public long PassagewayId { get; set; }

        /// <summary>
        /// 关联通道编号, 动态赋值
        /// </summary>
        public string PassagewayCode { get; set; }

        /// <summary>
        /// 关联通道名称,动态赋值
        /// </summary>
        public string PassagewayName { get; set; }


        /// <summary>
        /// 是否仅作为监控
        /// </summary>
        public bool OnlyMonitor { get; set; }

        /// <summary>
        /// 设备控制句柄,一般是dllimport 之类的硬件SDK赋值使用
        /// </summary>
        protected int _deviceHandle;

        /// <summary>
        /// 串口控制句柄
        /// </summary>
        protected int _serialPortHandle;

        public string RTSPUrl { get; set; }

        private DelegateCommand _onMouseEnterCmd;
        public DelegateCommand OnMouseEnterCmd =>
            _onMouseEnterCmd ?? (_onMouseEnterCmd = new DelegateCommand(ExecuteOnMouseEnterCmd));

        void ExecuteOnMouseEnterCmd()
        {
            MouseHover = true;
        }

        private DelegateCommand _onMouseLeaveCmd;
        public DelegateCommand OnMouseLeaveCmd =>
            _onMouseLeaveCmd ?? (_onMouseLeaveCmd = new DelegateCommand(ExecuteOnMouseLeaveCmd));

        void ExecuteOnMouseLeaveCmd()
        {
            MouseHover = false;
        }

        private DelegateCommand<Image> _deviceControlLoadCmd;
        public DelegateCommand<Image> DeviceControlLoadCmd =>
            _deviceControlLoadCmd ?? (_deviceControlLoadCmd = new DelegateCommand<Image>(ExecuteDeviceControlLoadCmd));

        void ExecuteDeviceControlLoadCmd(Image ctrl)
        {
            Init(ctrl);
            Task.Run(() => Open());
        }

        private bool _deviceBusyOrError;
        public bool DeviceBusyOrError
        {
            get { return _deviceBusyOrError; }
            set
            {
                SetProperty(ref _deviceBusyOrError, value);
            }
        }

        private string _message;
        public string Message
        {
            get { return _message; }
            set
            {
                SetProperty(ref _message, value);
            }
        }

        protected void SetBusyOrError(string msg)
        {
            DeviceBusyOrError = true;
            Message = msg;
        }

        protected Image _ctrl;

        protected DeviceReceiveCmdEvent _deviceReceiveCmdEvent;

        protected void Init(Image ctrl)
        {
            _ctrl = ctrl;

            _deviceReceiveCmdEvent = EventAggregator.GetEvent<DeviceReceiveCmdEvent>();

            _deviceReceiveCmdEvent.Subscribe(OnDeviceReceiveCmdEvent);
        }

        public virtual void Open()
        {

        }

        /// <summary>
        /// 强制触发车牌识别
        /// </summary>
        /// <returns></returns>
        public virtual Task<bool> RaiseCarPlatResultAsync()
        {
            return Task.FromResult(true);
        }

        /// <summary>
        /// 开关闸门
        /// </summary>
        /// <param name="open"></param>
        /// <returns></returns>
        public virtual Task<bool> ToggleGateSwitchCmdAsync(bool open)
        {
            return Task.FromResult(true);
        }


        protected virtual void OnDeviceReceiveCmdEvent(DeviceReceiveCmdEventArgs e)
        {

        }

        public virtual void Close()
        {

        }

        public virtual string GetCapture(string targetDir = null, string fileName = null)
        {

            if (string.IsNullOrWhiteSpace(IP))
            {
                return string.Empty;
            }
            targetDir = targetDir ?? Path.GetTempPath();
            fileName = fileName ?? $"{IP.ToString().MDString()}_{Direction}_{SnowFlake.GetInstance().GetUniqueShortId()}.jpg";
            var fileFullName = Path.Combine(targetDir, fileName);
            if (!System.IO.Directory.Exists(targetDir))
            {
                System.IO.Directory.CreateDirectory(targetDir);
            }
            try
            {
                _ctrl.Dispatcher.Invoke(() =>
                {
                    try
                    {
                        var imgSource = _ctrl.Source as BitmapSource;
                        if (imgSource == null)
                        {
                            return;
                        }
                        using (var fileStream = new FileStream(fileFullName, FileMode.OpenOrCreate))
                        {
                            var encoder = new JpegBitmapEncoder();
                            encoder.Frames.Add(BitmapFrame.Create(imgSource));
                            encoder.Save(fileStream);
                        }
                    }
                    catch (Exception)
                    {
                        fileFullName = string.Empty;
                    }

                });

                return fileFullName;
            }
            catch (Exception e)
            {
                Logger.Error($"{Type}:设备抓图失败", e);
            }

            return string.Empty;
        }

        public virtual void StartVideo()
        {
            if (string.IsNullOrWhiteSpace(IP) || string.IsNullOrWhiteSpace(RTSPUrl))
            {
                return;
            }

            // 这个必须赋值，重新显示主窗口后才能继续渲染图片
            _canRender = true;

            if (_videoCapture != null)
            {
                // 这里一定要返回，否则会触发重复调用ffmpeg导致一些问题
                return;
            }
            try
            {
                _videoCapture = new FFmpegRTSPCapture();
                _videoCapture.ImageGrabbed += OnVideoCaptureGrabbed;
                _videoCapture.Start(RTSPUrl);
            }
            catch (Exception ex)
            {
                Logger.Error($"{Type} 实时监控失败:{RTSPUrl}", ex);
                SetBusyOrError(ex.Message);
            }
        }

        public virtual void StopVideo()
        {
            if (string.IsNullOrWhiteSpace(IP))
            {
                return;
            }
            _canRender = false;
        }

        public virtual void ExitVideo()
        {
            if (string.IsNullOrWhiteSpace(IP))
            {
                return;
            }
            if (_videoCapture != null)
            {
                _videoCapture.ImageGrabbed -= OnVideoCaptureGrabbed;
                _videoCapture.Stop();
            }
            StopVideo();
        }

        private void OnVideoCaptureGrabbed(object sender, System.Drawing.Bitmap e)
        {
            _ctrl.Dispatcher.Invoke(() =>
            {
                if (!_canRender || _ctrl == null || e == null)
                {
                    return;
                }

                DeviceBusyOrError = false;
                Message = string.Empty;
                _ctrl.Source = BitmapSourceConvert.ToBitmapSource(e);

            });
        }
    }
}
